/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.incad.psh.pshassign.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
import cz.incad.psh.pshassign.client.json.ResultDoc;
import cz.incad.psh.pshassign.client.json.SearchData;
import cz.incad.psh.pshassign.client.rpc.PSHService;
import cz.incad.psh.pshassign.client.rpc.PSHServiceAsync;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;


import static com.google.gwt.query.client.GQuery.$;
import static gwtquery.plugins.ui.Ui.Ui;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.XMLParser;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author alberto
 */
public class PSHResults extends Composite {

    private static PSHResultsUiBinder uiBinder = GWT.create(PSHResultsUiBinder.class);
    PSHServiceAsync pshService = GWT.create(PSHService.class);
    @UiField
    FlowPanel resultsPanel;
    @UiField
    HTMLPanel content;
    @UiField
    ScrollPanel scrollPanel;
    @UiField
    Image loading;
    @UiField
    FlowPanel analisys;
    SearchData searchData;
    HashMap<String, ArrayList<String>> words = new HashMap<String, ArrayList<String>>();
    HashMap<String, ArrayList<String>> roots = new HashMap<String, ArrayList<String>>();
    HashMap<String, String> pshNames = new HashMap<String, String>();
    String id;

    interface PSHResultsUiBinder extends UiBinder<Widget, PSHResults> {
    }

    public PSHResults() {
        initWidget(uiBinder.createAndBindUi(this));
        loading.setVisible(false);
        analisys.getElement().setAttribute("id", "analisys");
    }

    void clear() {
        resultsPanel.clear();
        analisys.clear();
        words.clear();
        roots.clear();
        pshNames.clear();
    }
    
    public void showRankExplain(){
        
    }
    
    public void getKeys(String id) {
        this.id = id;
        clear();
        loading.setVisible(true);
        pshService.getPSHKeys(id, new AsyncCallback() {
            @Override
            public void onFailure(Throwable caught) {
                resultsPanel.add(new InlineHTML("error getting keys: "
                        + caught.getLocalizedMessage()));
            }

            @Override
            public void onSuccess(Object result) {
                try {
                    MainPage mainPage = (MainPage) RootLayoutPanel.get().getWidget(0);
                    loading.setVisible(false);
                    JSONObject js = JSONParser.parseStrict((String) result).isObject();
                    JSONArray keys = js.get("keys").isArray();
                    int max =  Math.min(keys.size(), mainPage.getIntOption("interface", "max_keys"));
                    for (int i = 0; i < max; i++) {
                        try {
                            JSONObject heslo = keys.get(i).isObject();
                            String uri = heslo.get("uri").isString().stringValue();
                            String root = heslo.get("root").isString().stringValue();

                            JSONObject hl = heslo.get("hlObject").isObject();
                            String[] paths = heslo.get("path").isString().stringValue().substring(1).split("/");
                            for (String path : paths) {
                                pshNames.put(path, "");
                            }
                            setWords(uri, root, hl);

                            resultsPanel.add(new Heslo(heslo));
                        } catch (Exception ex) {
                            Logger.getLogger(PSHResults.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                    HorizontalPanel hp = new HorizontalPanel();
                        Anchor bt = new Anchor("save");
                        bt.addClickHandler(new ClickHandler() {
                            @Override
                            public void onClick(ClickEvent event) {
                                save();
                            }
                        });
                        hp.add(bt);
                        Anchor bt2 = new Anchor("analisys");
                        bt2.addClickHandler(new ClickHandler() {
                            @Override
                            public void onClick(ClickEvent event) {
                                //dgAnalisys.center();
                                $("#analisys").as(Ui).dialog("{width:700, height: 480}");
                            }
                        });
                        hp.add(bt2);
                        $(bt).as(Ui).button();
                        $(bt2).as(Ui).button();
                        resultsPanel.insert(hp, 0);
                        analisys.setVisible(false);
                    scrollPanel.setPixelSize(content.getOffsetWidth(),
                            //mainPage.center.getOffsetHeight() - 
                            //content.getOffsetHeight() -
                            mainPage.center.getElement().getClientHeight()
                            - mainPage.docInfo.getOffsetHeight()
                            - 0);
                    final Timer timer = new Timer() {
                        @Override
                        public void run() {
                            getNames();
                            this.cancel();
                        }
                    };
                    timer.schedule(1000);
                } catch (Exception ex) {
                    Logger.getLogger(PSHResults.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });

    }
    private void getNames() {
        String path = "";
        Set keys = pshNames.keySet();
        for (Iterator iter2 = keys.iterator(); iter2.hasNext();) {
            path += "/" + (String) iter2.next();
        }
        try {
            pshService.getKeyNames(path, new AsyncCallback() {
                @Override
                public void onFailure(Throwable caught) {
//                    resultsPanel.add(new InlineHTML("error getting names: "
//                            + caught.getLocalizedMessage()));
                }

                @Override
                public void onSuccess(Object result) {

                    
                    SearchData js = SearchData.parseJson((String) result);
                    JsArray<ResultDoc> docs = js.getResults();
                    for (int i = 0; i < docs.length(); i++) {
                        ResultDoc doc = docs.get(i);
                        pshNames.put(doc.getField("id"), doc.getFieldArray("csPrefLabel").get(0));

                    }
                    fillAnalisys();
                    changePathInHeslo();
                    MainPage mainPage = (MainPage) RootLayoutPanel.get().getWidget(0);
                    scrollPanel.setPixelSize(content.getOffsetWidth(),
                        mainPage.center.getElement().getClientHeight()
                        - mainPage.docInfo.getOffsetHeight()
                        - 0);
                    
                    scrollPanel.setPixelSize(content.getOffsetWidth(),
                            content.getElement().getClientHeight() - 20);
                }
            });
        } catch (Exception ex) {
        }
    }

    private void changePathInHeslo() {
        for (int i = 1; i < resultsPanel.getWidgetCount(); i++) {
            Label p = ((Heslo) resultsPanel.getWidget(i)).path;
            String s = "";
            String[] ids = p.getText().split("/");
            for (int j =1; j< ids.length; j++) {
                s += "/" + pshNames.get(ids[j]);
            }
            p.setText(s);
        }
    }
    
    public void changeStrength(String strength){
        
        for (int i = 1; i < resultsPanel.getWidgetCount(); i++) {

            Heslo h = (Heslo) resultsPanel.getWidget(i);
            h.setStrength(strength);
        }
    }
    

    private String doXml() {
//        <record xmlns:java="http://xml.apache.org/xslt/java" >
//<controlfield tag="001">92755</controlfield>
//        <datafield ind2="7" ind1=" " tag="650">
//<subfield code="a">ptáci</subfield>
//<subfield code="2">PSH</subfield>
//</datafield>
//<datafield ind2="7" ind1=" " tag="650">
//<subfield code="a">změny</subfield>
//<subfield code="2">PSH</subfield>
//</datafield>
//<datafield ind2=" " ind1=" " tag="598">
//<subfield code="a">Hesla PSH byla přiřazena automatickou indexací.</subfield>
//</datafield>

        StringBuilder xml = new StringBuilder();
        xml.append("<record xmlns:java=\"http://xml.apache.org/xslt/java\" >");
        xml.append("<controlfield tag=\"001\">").append(this.id).append("</controlfield>");

        for (int i = 1; i < resultsPanel.getWidgetCount(); i++) {

            Heslo p = (Heslo) resultsPanel.getWidget(i);
            if (p.shouldSave()) {
                xml.append("<datafield ind2=\"7\" ind1=\" \" tag=\"650\">");
                xml.append("<subfield code=\"a\">").append(p.getLabel()).append("</subfield>");
                xml.append("<subfield code=\"2\">PSH</subfield>");
                xml.append("</datafield>");
            }
        }

        xml.append("<datafield ind2=\" \" ind1=\" \" tag=\"598\">");
        xml.append("<subfield code=\"a\">Hesla PSH byla přiřazena automatickou indexací.</subfield>");
        xml.append("</datafield>");
        xml.append("</record>");
        return xml.toString();

    }

    private String doXml2() {
//        <record xmlns:java="http://xml.apache.org/xslt/java" xmlns:exts="java://cz.incad.indexer_demo.XSLFunctions">
//<controlfield tag="001">92755</controlfield>
//        <datafield ind2="7" ind1=" " tag="650">
//<subfield code="a">ptáci</subfield>
//<subfield code="2">PSH</subfield>
//</datafield>
//<datafield ind2="7" ind1=" " tag="650">
//<subfield code="a">změny</subfield>
//<subfield code="2">PSH</subfield>
//</datafield>
//<datafield ind2=" " ind1=" " tag="598">
//<subfield code="a">Hesla PSH byla přiřazena automatickou indexací.</subfield>
//</datafield>
        Document doc = XMLParser.createDocument();

        Element e;
        Element record = doc.createElement("record");

        e = doc.createElement("controlfield");
        e.setAttribute("tag", "001");
        e.appendChild(doc.createTextNode(this.id));
        record.appendChild(e);
        for (int i = 1; i < resultsPanel.getWidgetCount(); i++) {

            Heslo p = (Heslo) resultsPanel.getWidget(i);

            if (p.shouldSave()) {

                Element datafield = doc.createElement("datafield");
                datafield.setAttribute("ind2", "7");
                datafield.setAttribute("ind1", " ");
                datafield.setAttribute("tag", "650");

                Element subfield = doc.createElement("subfield");
                subfield.setAttribute("code", "a");
                subfield.appendChild(doc.createTextNode(p.getLabel()));
                datafield.appendChild(subfield);

                subfield = doc.createElement("subfield");
                subfield.setAttribute("code", "2");
                subfield.appendChild(doc.createTextNode("PSH"));
                datafield.appendChild(subfield);

                record.appendChild(datafield);


                datafield = doc.createElement("datafield");
                datafield.setAttribute("ind2", " ");
                datafield.setAttribute("ind1", " ");
                datafield.setAttribute("tag", "598");

                subfield = doc.createElement("subfield");
                subfield.setAttribute("code", "a");
                subfield.appendChild(doc.createTextNode("Hesla PSH byla přiřazena automatickou indexací."));
                datafield.appendChild(subfield);

                record.appendChild(datafield);
            }
        }
        doc.appendChild(record);
        return doc.toString();
    }

    private void save() {
        String xml = doXml();
        pshService.saveToInvenio(xml, new AsyncCallback() {
            @Override
            public void onFailure(Throwable caught) {
                Window.alert("error saving to invenio: "
                        + caught.getLocalizedMessage());
            }

            @Override
            public void onSuccess(Object result) {

                Window.alert((String)result);
            }
        });


    }

    private void setWords(String uri, String root, JSONObject uriObject) {
        Set fields = uriObject.keySet();
        for (Iterator iter2 = fields.iterator(); iter2.hasNext();) {
            String field = (String) iter2.next();
            //analisys.add(new Label("field: " + field));
            JSONArray fArray = uriObject.get(field).isArray();
            for (int k = 0; k < fArray.size(); k++) {
                String hl = fArray.get(k).isString().stringValue();
                for (String word : getWords(hl)) {
                    if (words.containsKey(word)) {
                        ArrayList wroots = words.get(word);
                        if (!wroots.contains(root)) {
                            wroots.add(root);
                        }
                    } else {
                        ArrayList wroots = new ArrayList<String>();
                        wroots.add(root);
                        words.put(word, wroots);
                    }


                    if (roots.containsKey(root)) {
                        ArrayList rwords = roots.get(root);
                        if (!rwords.contains(word)) {
                            rwords.add(word);
                        }
                    } else {
                        ArrayList rwords = new ArrayList<String>();
                        rwords.add(word);
                        roots.put(root, rwords);
                    }
                }
            }
        }
    }

    private ArrayList<String> getWords(String cs) {
        ArrayList<String> list = new ArrayList<String>();
        String patternStr = "<b>(.*?)<\\/b>";
        RegExp regExp = RegExp.compile(patternStr, "ig");
        
        for (MatchResult matcher = regExp.exec(cs); matcher != null; matcher = regExp.exec(cs)) {
            //matches.add(matcher.getGroup(0));
            list.add(matcher.getGroup(1));
         }
        
        return list;
    }

    private void fillAnalisys() {
        Set keys = words.keySet();
        for (Iterator iter2 = keys.iterator(); iter2.hasNext();) {
            String word = (String) iter2.next();
            analisys.add(new Label(word));
            for (String root : words.get(word)) {
                final FocusPanel fc = new FocusPanel();
                fc.setStyleName(root);
                fc.addMouseOverHandler(new MouseOverHandler() {
                    @Override
                    public void onMouseOver(MouseOverEvent event) {
                        String c = fc.getStyleName();
                        $("#analisys>div." + c).addClass("ui-state-error-text");
                        $("#analisys>div." + c + " a").addClass("ui-state-error-text");
                    }
                });

                fc.addMouseOutHandler(new MouseOutHandler() {
                    @Override
                    public void onMouseOut(MouseOutEvent event) {
                        $("#analisys>div").removeClass("ui-state-error-text");
                        $("#analisys>div a").removeClass("ui-state-error-text");
                    }
                });
                fc.add(new InlineHTML("&nbsp;<a class=\"root " + root + "\" target=\"_blank\" href=\"http://psh.ntkcz.cz/skos/" + root + "\">" + pshNames.get(root) + " (" + root + ")</a> - "
                        + (roots.get(root).size() - 1)));
                analisys.add(fc);
            }
        }
    }
}
